﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.ComponentModel.DataAnnotations;
using System.Web.Mvc;

namespace IceTea.Domain.Models
{
    [MetadataType(typeof(MetadataRelease))]
    public partial class Release : IValidatableObject
    {
        public Release()
        {
            this.Id = -1;
        }

        public class MetadataRelease
        {
            [Required(ErrorMessage="Please enter the title of release", AllowEmptyStrings=false)]
            [Display(Name="Title")]
            [DisplayFormat(ConvertEmptyStringToNull=false)]
            public string Title { get; set; }

            [Display(Name="Description")]
            [DisplayFormat(ConvertEmptyStringToNull=false)]
            public string Description { get; set; }

            [Display(Name="Start Date")]
            [DataType(DataType.Date)]
            [DisplayFormat(DataFormatString="D", ApplyFormatInEditMode=true)]
            public DateTime StartDate { get; set; }

            [Display(Name="End Date")]
            [DataType(DataType.Date)]
            [DisplayFormat(DataFormatString = "D", ApplyFormatInEditMode=true)]
            public DateTime EndDate { get; set; }

            [HiddenInput(DisplayValue=false)]
            public int Id { get; set; }

            [HiddenInput(DisplayValue=false)]
            public int ProductId { get; set; }
        }

        #region Implements of IValidatableObject
        public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
        {
            List<ValidationResult> errors = new List<ValidationResult>();
            if (IsTitleUnique() == false)
            {
                errors.Add(new ValidationResult("Please make sure the Title is unique in current product"));
            }
            if (DateTime.Compare(StartDate, EndDate) >= 0)
            {
                errors.Add(new ValidationResult("End Date should not be earlier than the Start Date"));
            }
            if (IsDateOverlap())
            {
                errors.Add(new ValidationResult("Start Date and End Date should not overlap with other releases"));
            }
            return errors;
        }
        #endregion

        /// <summary>
        /// Looks for whether the StartDate and EndDate overlap with other releases in this product
        /// </summary>
        /// <returns></returns>
        protected bool IsDateOverlap()
        {
            using (IceTeaEntities ite = new IceTeaEntities())
            {
                if (this.Id <= 0)
                {
                    if (ite.Releases.Any(r => r.ProductId == this.ProductId
                                   && ((r.StartDate <= this.StartDate && r.EndDate >= this.StartDate)
                                    || (r.StartDate <= this.EndDate && r.EndDate >= this.EndDate)
                                    || (r.StartDate >= this.StartDate && r.EndDate <= this.EndDate)))
                                    == true)
                        return true;
                }
                else
                {
                    if (ite.Releases.Any(r => r.ProductId == this.ProductId && r.Id != this.Id
                                   && ((r.StartDate <= this.StartDate && r.EndDate >= this.StartDate)
                                    || (r.StartDate <= this.EndDate && r.EndDate >= this.EndDate)
                                    || (r.StartDate >= this.StartDate && r.EndDate <= this.EndDate)))
                                    == true)
                        return true;
                }
            }
            return false;
        }

        /// <summary>
        /// Is the current Release title is unique in records
        /// </summary>
        /// <returns></returns>
        protected bool IsTitleUnique()
        {
            using (IceTeaEntities ite = new IceTeaEntities())
            {
                if (this.Id <= 0) //new release object
                {
                    if (ite.Releases.Any(r => r.Title == this.Title && r.ProductId == this.ProductId)
                        == true)
                        return false;
                }
                else //an exisiting release object
                {
                    if (ite.Releases.Any(r => r.Title == this.Title && r.Id != this.Id && r.ProductId == this.ProductId)
                        == true)
                        return false;
                }
            }
            return true;
        }

        public void CopyFrom(Release release)
        {
            this.Title = release.Title;
            this.Description = release.Description;
            this.StartDate = release.StartDate;
            this.EndDate = release.EndDate;
        }
    }
}
